package com.hejia.alauda.service;

import com.hejia.alauda.entity.*;
import com.hejia.alauda.entity.example.FinancingExample;
import com.hejia.alauda.entity.example.InterestExample;
import com.hejia.alauda.entity.example.RedemptionRequestExample;
import com.hejia.alauda.utils.Pager;

import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;

/**
 * Created by Johnny(johnny@hejiajinrong.com) on 15/3/2.
 */

@Service
public interface BalanceAndFinancingService {

    /******  FinancialAsset   ******/


    /**
     * 查找金融资产
     *
     * @param keyword
     *            关键词
     * @param valueDateStart
     *            起息日从
     * @param valueDateEnd
     *            起息日到
     * @param dueDateStart
     *            到期日从
     * @param dueDateEnd
     *            到期日到
     * @param pager
     *            分页
     * @return 金融资产列表
     */
    Pager<FinancialAsset> findFinancialAssets(String keyword,
                                              Date valueDateStart, Date valueDateEnd, Date dueDateStart,
                                              Date dueDateEnd, Pager<FinancialAsset> pager);


    /**
     * 添加金融资产
     *
     * @param financialAsset
     *            金融资产
     * @return 金融资产
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    FinancialAsset addFinancialAsset(FinancialAsset financialAsset);


    /**
     * 根据金融资产ID查找
     *
     * @param id
     *            金融资产ID
     * @return 金融资产
     */
    FinancialAsset findFinancialAssetById(Long id);

	/**
	 * 根据银行卡号获取该银行卡下未回款资产包数
	 * 
	 * @param bankCardId
	 * @return
	 */
	Pager<Financing> findUnrepaidFinancing(Long bankCardId);


    /**
     * 更新金融资产
     *
     * @param financialAsset
     *            金融资产
     * @return 金融资产
     */
    FinancialAsset updateFinancialAsset(FinancialAsset financialAsset);

    /**
     * 根据ID删除金融资产
     *
     * @param id
     *            金融资产ID
     * @throws Exception
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void deleteFinancialAssetById(Long id) throws Exception;

    /**
     * 查找金融资产库存
     *
     * @return 金融资产库存
     */
    List<FinancialAsset> findFinancialAssetInventory();

    /**
     * 查找金融资产的产品结息日列表
     *
     * @param financialAssetId
     *            金融资产ID
     * @return 产品结息日列表
     */
    List<ProductSettlementDate> findProductSettlementDatesByFinancialAssetId(
            Long financialAssetId);

    /**
     * 查找金融资产产品结息日列表
     *
     * @param productId
     *            金融资产产品ID
     * @return 产品结息日列表
     */
    List<ProductSettlementDate> findProductSettlementDatesByProductId(
            Long productId);


    /********* FinancialAssetStockEntry *********/
    /**
     * 查找出入库记录
     * @param id	金融资产ID
     * @return		出入库记录
     */
    List<FinancialAssetStockEntry> findStockEntriesByFinancialAssetId(Long id);

    /**
     * 查找指定金融资产的出入库列表
     * @param financialAssetId	金融资产ID
     * @return
     */
    List<FinancialAssetStockEntry> findEntriesByFinancialAssetId(Long financialAssetId);


    /***** FinancialAssetStock ******/
    /**
     * 入库
     * @param financialAssetStockEntry	金融资产出入库记录
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void inStock(FinancialAssetStockEntry financialAssetStockEntry);

    /**
     * 出库
     * @param financialAssetStockEntry	金融资产出入库记录
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void outStock(FinancialAssetStockEntry financialAssetStockEntry);

    /**
     * 产品销售结束，调整库存。
     * 未售金额入库，超卖金额出库。
     * @param productId	产品ID
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void productSellCloseAdjustStock(Long productId);

    /**
     * 计算指定日期用户回款金额入库
     * @param date	日期
     */
    void calculatePaymentCollectionInStock(Date date);

    /**
     * 添加出入库记录
     * @param financialAssetStockEntry
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void addFinancialAssetStockEntry(
            FinancialAssetStockEntry financialAssetStockEntry);

    /**
     * 删除出入库记录
     * @param id	出入库记录ID
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void deleteFinancialAssetStockEntryById(Long id);

    /**
     * 计算指定时间金融资产库存
     * @param financialAssetId	金融资产ID
     * @param date 				计算时间
     * @return					金融资产库存
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    BigDecimal calculateFinancialAssetStock(Long financialAssetId, Date date);

    /**
     * 更新金融资产库存
     * @param financialAssetId	金融资产ID
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void updateFinancialAssetStock(Long financialAssetId);

    /**
     * 重建出入库记录
     * @param financialAssetId
     */
    void recreateFinancialAssetStockEntry(Long financialAssetId);


    /**
     * 根据条件来查询金融包
     * @param example
     * @param pager
     * @return
     */
    List<Financing> findFinancingByExample(FinancingExample example,Pager<Financing> pager);

    /**
     * 根据ID查询金融包
     * @param id
     * @return
     */
    Financing findFinancingById(Long id);
    /**
     * 更新用户金融包
     * @param financing
     * @return
     */
    boolean updateFinancing(Financing financing);

    /**
     * 计算金融包的每天的利息
     * @param financing
     * @return
     */
    boolean calculateInterest(Financing financing);

    /**
     * 计算金融包的利息
     * @param financing
     */
    void createDayInterest(Financing financing);

    /**
     * 根据financing_id查利息
     * @param financing
     */
    List<Interest> getInterestByExample(InterestExample example);

    /**
     * 根据financing_id查利息的行数
     * @param financing
     */
    int getInterestCountByExample(InterestExample example);


    void calculate(AsyncTaskExecutor executor);

    /**
     * 重新计算资产记录的利息
     * @return
     */
    //boolean refreshInterest(Financing financing);


    List<Financing> findFinancingByValueDate(String valueDate);

    List<Financing> findFinancingByCreateDate(String valueDate);
    
    /**
     * 根据产品id查询销量排名前10的资产列表
     * @param product_id
     * @return
     */
    List<Financing> findFinancingTop10ByProductId(Long product_id);
    
    /**
     * 给2015年三月送流量的活动查询是否到一万元的资格（除新手产品）
     * @param params
     * @return
     */
    BigDecimal findTotalAmountForMarchTraffic2015(Map<String, Object> params);
    
    /**
     * 判断用户活动期间总消费数量是否满足条件
     * @param amount 消费金额数量要求(BigDecimal)
     * @param start 活动开始时间
     * @param end 活动结束时间 
     * @param userId 用户ID (Long)
     * 
     * @return true or false
     * */
    boolean findActivityIntervelAmounts(Map<String, Object> params);
    
    /**
     * 查询用户的最新一条资产记录
     * @param user
     * @return
     */
    Financing findLatestFinancingByUser(User user);

    /**
     * 判断用户活动期间单笔消费数量是否满足条件
     * @param amount 消费金额数量要求(BigDecimal)
     * @param start 活动开始时间
     * @param end 活动结束时间 
     * @param userId 用户ID (Long)
     * 
     * @return true or false
     * */
	boolean findSingleAmount(Map<String, Object> params);
	
	/**
	 * 判断用户活动期间单笔消费数量是否满足条件
	 * @param amount 消费金额数量要求(BigDecimal)
	 * @param start 活动开始时间
	 * @param end 活动结束时间 
	 * @param userId 用户ID (Long)
	 * 
	 * @return true or false
	 * */
	boolean findSingleAmountBy51(Map<String, Object> params);
    
    /**
     * 根据条件查询赎回申请的记录
     * @return
     */
    Integer saveRedemptionRequest(Financing financing);
    
    /**
     * 补充老数据的资产钱滚翻收益规则
     * @param id
     */
    void addFinancingIncomeRules(Long id);
    
    /**
     * 根据条件统计资产总和
     * @param params
     * @return
     */
    BigDecimal findTotalAmountByProperty(Map<String, Object> params);
    
    /**
     * 根据条件查询用户总金额的排名
     * @param params
     * @return
     */
    List<Financing> findFinancingRankByProperty(Map<String, Object> params);
    
    /**
     * 根据条件查询个体用户的资产排名情况
     * @param params
     * @return
     */
    List<Financing> findUserFinancingRankByProperty(Map<String, Object> params);

    /**
     * 查询申请打款资产列表
     * @param pager
     * @param keyword	关键词
     * @param settlementDate	兑付日
     */
	void findApplyFinancingByKeywordAndDate(Pager<Financing> pager, String keyword, Date settlementDate);
	
	/**
	 * 判断用户的资产是否有在兑付期内多少天的
	 * @param user
	 * @return
	 */
	boolean hasBondQualification(User user);
	
	/**
	 * 判断用户的江湖地位
	 * @param user
	 * @return
	 */
	int checkClassify(User user);
	
	/**
	 * 用户保底收益
	 * @param financing
	 * @param totalInterest
	 */
	public void createMinTermInterest(Financing financing, BigDecimal interest, BigDecimal totalInterest);
	/**
	 * 获取资产创造的收益
	 * @return
	 */
	public BigDecimal getTatalIncomeForUer();
	
	public Long calculate(Financing financing);
	
	//单日利息
	public BigDecimal calculateInterest(Financing financing, int days);

}
